
import unittest

class TestBuiltInFunctions(unittest.TestCase):
    """
    test some features that cannot be categorized into other module
    """
    
    def test_multipe_assignment(self):
        x = 1
        y = 2
        x,y = y,x
        
        self.assertEqual(2,x)
        self.assertEqual(1,y)
        
    def test_compare(self):
        self.assertTrue(cmp(12,4) > 0)
        self.assertTrue(cmp("cheka","stasi") < 0)
        
    def test_max_min(self):
        names = ("cheka","Stasi","mss")
        self.assertEqual("Stasi",min(names)) # upper characters are always before lower characters
        self.assertEqual("mss",max(names))
        
    def test_sorted(self):
        names = ("cheka","Stasi","mss")
        # sorted return a wholely new array, the input array will remainn not changed
        self.assertEqual(["Stasi","cheka","mss"],sorted(names))
        
        # reversed return back an iterator, not a sequence
        reversed_names = []
        for item in reversed(names):
            reversed_names.append(item)
        self.assertEqual(["mss","Stasi","cheka"],reversed_names)
        
    def test_sum(self):
        # sum cannot be used with type "str"
        # use "join" to concatenate strings
        
        # ------------------------- without seed, default seed = 0
        self.assertEqual(6,sum((1,2,3)))
        
        # ------------------------- sum based on the second parameter, a given seed 
        self.assertEqual(20,sum([4,5,6],5))
        
    def test_zip(self):
        alist = [1,2]
        atuple = ("cheka","stasi","mss")
        self.assertEqual([("cheka",1),("stasi",2)],zip(atuple,alist))
        
    def test_tripple_operator(self):
        """
        python doesn't provide 'tripple operator', but can be simulated in below way
        """
        my_min = lambda x,y: x if x < y else y
        my_max = lambda x,y: x if x > y else y
        
        a = 100
        b = 50
        self.assertEqual(a,my_max(a,b))
        self.assertEqual(b,my_min(a,b))
        
    def test_range(self):
        """
        pay attention, the first argument is start, default to one
        and the second parameter is end, not size
        """
        self.assertEqual([2,3,4],range(2,5))
        self.assertEqual([0,3,6],range(0,8,3))
        

    def test_any_all(self):
        alist = [1,3,5,6]
        
        def is_even_generator():
            for item in alist:
                yield item % 2 == 0
        
        # any, all only accept an iterator, no predicate can be provide
        # you have to define generator to translate each item into boolean
        self.assertTrue(any(is_even_generator()))
        self.assertFalse(all(is_even_generator()))
        
if __name__ == "__main__":
    unittest.main()